﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

using agree.schema;

using alib;
using alib.Debugging;
using alib.Observable;

namespace agree
{
#if true
	public class UnpackLoader : m_scalar_base<IChartControl, DerivationSet>,
		ρρTfsUnifier
	{
		public UnpackLoader(IRtParent parent, IChartControl chart)
			: base(parent, chart)
		{
		}

		///////////////////////////////////////////////////////////////////////
		///
		public TfsUnifier u;
		public TfsUnifier TfsUnifier
		{
			get { return this.u; }
			set { this.u = value; }
		}
		///
		///////////////////////////////////////////////////////////////////////


		///////////////////////////////////////////////////////////////////////
		///
		//int c_input;
		//public override int InputItemsCount
		//{
		//	get { return c_input; }
		//}
		///
		///////////////////////////////////////////////////////////////////////


		protected override DerivationSet start(IChartControl ctrl)
		{
			return ctrl.Forest.Unpack.ValidateAll;
		}
	};

#else
	public class UnpackLoader : m_observable<IChartControl, IDerivation>,
		ρρTfsUnifier
	{
		public UnpackLoader(IRtParent parent, IChartControl chart)
			: base(parent, chart)
		{
		}

		///////////////////////////////////////////////////////////////////////
		///
		public TfsUnifier u;
		public TfsUnifier TfsUnifier
		{
			get { return this.u; }
			set { this.u = value; }
		}
		///
		///////////////////////////////////////////////////////////////////////


		///////////////////////////////////////////////////////////////////////
		///
		int c_input;
		public override int InputItemsCount
		{
			get { return c_input; }
		}
		///
		///////////////////////////////////////////////////////////////////////

#if true
		protected override void start(IChartControl arg)
		{
			foreach (var d in t0.Forest)
			{
				var co = d as IChartObj;
				if (co != null)
				{
					if (co.IsHoldOrRemove())
						throw new Exception();

					if (!((ParseControl)arg).IsSpanning(co))
						throw new Exception();
				}

				var po = d as IPacking;
				if (po == null)
					_item(d);
				else
					unpack_items(po);
			}
			_remove_task();
		}

#else
		IEnumerable<IRootDerivationChartObj> get_input()
		{
			var e = t0.RootObjs.GetEnumerator();
			while (e.MoveNext())
			{
				c_input++;
				yield return e.Current;
			}
		}

		protected override void start(IChartControl arg)
		{
			foreach (var co in get_input())
			{
				if (co.IsHoldOrRemove())
					throw new Exception();

				if (!((ParseControl)arg).IsSpanning(co))
					throw new Exception();

				var po = co as IPacking;
				if (po == null)
					_item(co);
				else
					unpack_items(po);
			}
			_remove_task();
		}
#endif

		void unpack_items(IPacking po)
		{
			Tfs tfs;
			var gctrl = t0 as GenControl;

			foreach (IRootDerivation deriv in po.Derivations)
			{
				if ((tfs = deriv.DerivationTfs()) == null)
					continue;
#if false
				if (gctrl != null)
				{
					var mrsm = tfs.mrsm;
					TfsSlot ts = tfs[mrsm.InitialSemanticsPath];
					TfsSlot[] new_rels = mrsm.GetRelSlots(ts);

					if (new_rels.Length != gc.input.Rels.Length ||
						!gc.fsu.RelMatchHelper.CompareRels(gc.input.ts_mrs, ts, false, false))
					{
						Debug.Print("final semantics check failed");
						continue;
					}
				}
#endif
				_item(deriv);
			}
		}
	};
#endif
}